package com.gss.security.web;

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import org.apache.log4j.Logger;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.json.JSONArray;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import com.gss.armory.domain.DocAttDTO;
import com.gss.armory.domain.DocGeneralDetailsDTO;
import com.gss.armory.domain.DocumentTrackDetailsDTO;
import com.gss.armory.domain.UserActivityGroup;
import com.gss.armory.form.DocDetailsForm;
import com.gss.armory.form.UserSearchForm;
import com.gss.armory.persistence.CommonDAO;
import com.gss.armory.service.ProcessDocumentService;
import com.gss.common.util.ApplicationConstants;
import com.gss.common.util.ApplicationMaps;
import com.gss.security.domain.DocumentSearchDetails;
import com.gss.security.domain.UserDetailsDTO;
import com.gss.security.service.AuthenticationService;

@Controller
public class ViewDocumentController {

	private Logger logger = Logger.getLogger(ViewDocumentController.class);
	
	@Autowired
	private ProcessDocumentService processDocumentService;
	
	@Autowired
	CommonDAO commonDAO;
	
	@Autowired
	AuthenticationService authenticationService;
	
	@RequestMapping(value="downloadAttachmentFromReports.htm")
	public void downloadAttachmentFromReports(@RequestParam long docId,HttpServletResponse response) throws Exception{
		logger.debug("inside method downloadAttachment for id: "+docId);
		openDocumentAndSavetrackDetails(docId, response, docId);
	}
	
	@RequestMapping(value="downloadAttachment/{docId}.htm")
	public void downloadAttachment(@PathVariable long docId,HttpServletResponse response) throws Exception{
		logger.debug("inside method downloadAttachment for id: "+docId);
		openDocumentAndSavetrackDetails(docId, response, docId);
	}
	
	@RequestMapping(value="downloadLinkedAttachment/{docId}/{linkedDocId}.htm")
	public void downloadLinkedAttachment(@PathVariable long docId,@PathVariable long linkedDocId,HttpServletResponse response) throws Exception{
		logger.debug("inside method downloadAttachment for id: "+docId);
		openDocumentAndSavetrackDetails(docId, response, linkedDocId);
	}
	
	private boolean openDocumentAndSavetrackDetails(long docId, HttpServletResponse response, long linkedDocId) throws IOException{
		DocAttDTO attDTO = processDocumentService.getAttachment(docId,linkedDocId);
		
		boolean isDownloaded = false;
				
		if(null != attDTO){
			if(attDTO.getAttachEncrypted()!=null){
				response.setContentType("application/pdf");
				response.addHeader("Content-Disposition", "filename="+ attDTO.getAtt_orig_filename());
				OutputStream outputStream = response.getOutputStream();
				outputStream.write(attDTO.getAttachEncrypted());
				outputStream.flush();
				isDownloaded = true;
			}
			else{
				response.getWriter().write("You do not have the rights to view/print this document.");
			}
		}
		else
			response.getWriter().write("Internal Server Error. No Attachment found in Database");
		
		boolean resultOfSavingTrackDetails = false;
		
		if(isDownloaded){
		
			UserDetailsDTO userDetailsDTO = (UserDetailsDTO) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
			
			DetachedCriteria activityCriteria = DetachedCriteria.forClass(UserActivityGroup.class);
			activityCriteria.add(Restrictions.eq("username", userDetailsDTO.getUsername()));
			activityCriteria.add(Restrictions.eq("docId", docId));
			List<UserActivityGroup> activityEntry = commonDAO.loadAllByCriteria(activityCriteria);
			
			if(null != activityEntry && activityEntry.size() > 0){
				DocumentTrackDetailsDTO trackDetails = new DocumentTrackDetailsDTO();
				trackDetails.setDocId(docId);
				trackDetails.setTimeStamp(new Date());
				trackDetails.setPermission(activityEntry.get(0).getActivityType());
				trackDetails.setUserId(userDetailsDTO.getUsername());
				
				resultOfSavingTrackDetails = commonDAO.saveActivityTrackDetails(trackDetails);
				logger.debug("Track Detail is: " + (resultOfSavingTrackDetails?"saved.":"not saved."));
			}
		}
		return resultOfSavingTrackDetails;
	}
	
	@RequestMapping(value="embedPDF.htm")
	public ModelAndView getEmbedPdfView(@RequestParam long docId){
		logger.debug("inside getEmbedPDFview method ---> docId to load: " + docId);
		ModelAndView mav = new ModelAndView("workFlow/embeddedPDFDoc");
		mav.addObject("docId", docId);
		return mav;
	}
	@RequestMapping(value="updateWorkflow.htm")
	public ModelAndView updateWorkflow(@Valid @ModelAttribute(value="docDetailsForm") DocDetailsForm detailsForm,BindingResult bindingResult)
	{
		ModelAndView modelAndView = new ModelAndView("viewUploadDoc/viewDocAttachmentDetails");
		logger.debug(bindingResult.getErrorCount());
		modelAndView.addObject("docDetailsForm", detailsForm);
		return modelAndView;
	}
    @RequestMapping("/userLookUpPage")
    public ModelAndView userLookUp(){
        ModelAndView modelAndView = new ModelAndView();
       
        modelAndView.addObject("deptList", ApplicationMaps.DEPTID_DEPTSNAME_MAP);
//        modelAndView.addObject("locationList", ApplicationMaps.LOCID_LOCNAME_MAP);
        modelAndView.addObject("locationList", ApplicationMaps.getLocationMapForCurrentUser());
       
        modelAndView.setViewName("userLookUp");
        return modelAndView;
       
       
    }
   
   
    @RequestMapping("/documentLookUpPage.htm")
    public ModelAndView documentLookUp(@RequestParam(required=false,value="functionalityName",defaultValue="general") String functionalityName){
        ModelAndView modelAndView = new ModelAndView();       
        modelAndView.addObject("deptList", ApplicationMaps.DEPTID_DEPTSNAME_MAP);
//        modelAndView.addObject("locationList", ApplicationMaps.LOCID_LOCNAME_MAP);
        modelAndView.addObject("locationList", ApplicationMaps.getLocationMapForCurrentUser());
        modelAndView.addObject("docTypeMap",ApplicationMaps.DOCUMENT_TYPE_ID_NAME_MAP);
        HashMap<String, String> docStatusMap = new HashMap<String, String>();
        docStatusMap.put(DocGeneralDetailsDTO.DocumentFlowStatus.Active.toString(), "Active");
        if(null != functionalityName && !functionalityName.equals("general")){
        	if(functionalityName.equals("versionChange") || functionalityName.equals("changePermission") || functionalityName.equals("linkingDelinking")){
        		docStatusMap.put(DocGeneralDetailsDTO.DocumentFlowStatus.Active.toString(), "Active");
//        		docStatusMap.put(DocGeneralDetailsDTO.DocumentFlowStatus.Due.toString(), "Due");
//        		docStatusMap.put(DocGeneralDetailsDTO.DocumentFlowStatus.Overdue.toString(), "Overdue");
        	}else if(functionalityName.equals("activationDeactivation")){
        		docStatusMap.put(DocGeneralDetailsDTO.DocumentFlowStatus.Active.toString(), "Active");
//        		docStatusMap.put(DocGeneralDetailsDTO.DocumentFlowStatus.Due.toString(), "Due");
//        		docStatusMap.put(DocGeneralDetailsDTO.DocumentFlowStatus.Overdue.toString(), "Overdue");
        		docStatusMap.put(DocGeneralDetailsDTO.DocumentFlowStatus.Deactive.toString(), "Deactive");
        	}
        	else if(functionalityName.equals("changeVault")){
        		docStatusMap.put(DocGeneralDetailsDTO.DocumentFlowStatus.Active.toString(), "Active");
//        		docStatusMap.put(DocGeneralDetailsDTO.DocumentFlowStatus.Due.toString(), "Due");
//        		docStatusMap.put(DocGeneralDetailsDTO.DocumentFlowStatus.Overdue.toString(), "Overdue");
        		docStatusMap.put(DocGeneralDetailsDTO.DocumentFlowStatus.Expired.toString(), "Expired");
        		docStatusMap.put(DocGeneralDetailsDTO.DocumentFlowStatus.Versioned.toString(), "Versioned");
        	}
        }
        
        modelAndView.addObject("docStatusMap",docStatusMap);
        DocumentSearchDetails documentSearchDetails = new DocumentSearchDetails();
        modelAndView.addObject(documentSearchDetails);
        modelAndView.setViewName("documentLookUp");
        return modelAndView;
    }
   
	@RequestMapping("/userLookUpPage1.htm")		
	public ModelAndView userLookUpPage(HttpServletRequest httpServletRequest, @ModelAttribute UserSearchForm userSearchForm){
		logger.debug("method(userLookUpPage)");
		ModelAndView modelAndView=new ModelAndView();			
//		modelAndView.addObject("locName", ApplicationMaps.LOCID_LOCNAME_MAP);
		modelAndView.addObject("locName", ApplicationMaps.getLocationMapForCurrentUser());
		modelAndView.addObject("deptName" ,ApplicationMaps.DEPTID_DEPTSNAME_MAP);
		
		List<UserDetailsDTO> userDetailsDTOs = new ArrayList<UserDetailsDTO>();
		List<String> list = new ArrayList<String>();
		if(null != userSearchForm.getRole() && !userSearchForm.getRole().equals("")){
			logger.debug("searching user with role: " + userSearchForm.getRole());
			list = authenticationService.searchUserForRole(userSearchForm.getUserId(),userSearchForm.getRole());
		}
		if(!userSearchForm.getRole().isEmpty() && null != list && !list.isEmpty()){
			for(String stringUserId:list){
				userSearchForm.setUserId(stringUserId);
				List<UserDetailsDTO> detailsDTOs = processDocumentService.searchedUserData(userSearchForm);
				if(detailsDTOs!=null && detailsDTOs.size()>0){
					userDetailsDTOs.add(detailsDTOs.get(0));
				}
			}
		}
		else{
			if(userSearchForm.getRole().isEmpty()){
				userDetailsDTOs = processDocumentService.searchedUserData(userSearchForm);
			}
		}
		if(userDetailsDTOs.isEmpty()){
			modelAndView.addObject("resultOfsearch", true);
//			modelAndView.addObject("errorMsg" , "No user found according to the selected criteria.");
		}else{
			modelAndView.addObject("detailsList" , userDetailsDTOs);
		}		
		modelAndView.setViewName("userLookUpPage1");		
		return modelAndView;
	}
	
	@RequestMapping("/documentLookUpPage1.htm")
	public ModelAndView documentLookUpPage(HttpServletRequest httpServletRequest, @ModelAttribute DocumentSearchDetails documentSearchDetails){
		logger.debug("inside method(documentLookUpPage)");
		ModelAndView modelAndView=new ModelAndView();
		
//		Set<DocGeneralDetailsDTO> docGeneralDetailsSet = processDocumentService.searchedDocumentdata(documentSearchDetails);
		List<DocGeneralDetailsDTO> docGeneralDetailsSet  = processDocumentService.searchDocumentDataForDocumentLookup(documentSearchDetails);
		if(docGeneralDetailsSet.isEmpty()){			
			modelAndView.addObject("docerrorMsg" , "No document found according to the selected criteria.");
		}else{
			modelAndView.addObject("docdetailsList" , docGeneralDetailsSet);
		}
		logger.debug("Number of documents found: " + docGeneralDetailsSet.size());
//		modelAndView.addObject("locName", ApplicationMaps.LOCID_LOCNAME_MAP);
		modelAndView.addObject("locName", ApplicationMaps.getLocationMapForCurrentUser());
		modelAndView.addObject("deptName" , ApplicationMaps.DEPTID_DEPTSNAME_MAP);
		modelAndView.addObject("docTypeName" , ApplicationMaps.DOCUMENT_TYPE_ID_NAME_MAP);
		modelAndView.addObject("docCatName" , ApplicationMaps.DOCUMENT_CAT_ID_MAP);
		modelAndView.addObject("docSubCatName" , ApplicationMaps.DOCUMENT_SUB_CAT_ID_MAP);		
		modelAndView.setViewName("documentLookUpPage1");
		
		return modelAndView;
	}
	
	@RequestMapping(value="fetchUser")
	public void fetchuser(@ModelAttribute UserSearchForm userSearchForm,HttpServletResponse response){
		logger.debug("inside method(fetchUser)");
		
		List<UserDetailsDTO> detailsDTOs = (List<UserDetailsDTO>) processDocumentService.searchedUserData(userSearchForm);
		JSONArray array = new JSONArray();
		HashMap<String, String> hashMap = null;
		if(null != detailsDTOs){
			for (UserDetailsDTO idNameArray : detailsDTOs) {
				hashMap = new HashMap<String, String>();
				hashMap.put("optionValue", idNameArray.getUsername());
				hashMap.put("optionDisplay", idNameArray.getUserDisplayName());
				array.put(hashMap);
			}
			try {
				response.getWriter().write(array.toString());
			} catch (IOException e) {
				//e.printStackTrace();
				logger.error(e.getMessage());
			}
			
		}
	}
}
